<template>
  <div>
    <span>雷：</span
    ><el-input-number v-model="userTotal" :min="1"></el-input-number>
    &nbsp;
    <span>规格：</span
    ><el-input-number v-model="userNum" :min="1"></el-input-number>
    &nbsp;
    <el-button @click="resetGrid">确定</el-button>
    &nbsp;
    <div v-if="gridBomb" style="color: red">清除成功!!!</div>
    <div>TIP:点0可显示周围8个格子</div>
    <div class="center" :style="gridWidth">
      <el-button
        class="button"
        v-for="item in grid"
        :class="item.isShow ? 'buttonClick' : ''"
        @click="clickNum(item.index)"
        @click.right="flag(item)"
        >{{
          item.isShow ? item.bombNum : item.isflag ? item.isflag : ""
        }}</el-button
      >
    </div>
  </div>
</template>
<script setup>
import { ref, reactive, computed, onBeforeUnmount } from "vue";
import { ElMessage } from "element-plus";
const grid = reactive([]);
const num = ref(10);//格子规格初始值
const userNum = ref(10);//用户自定义格子规格
const gridWidth = computed(() => {
  return "width:" + num.value * 50 + "px";//格子样式-正方形
});
const gridBomb = computed(() => {
  return grid.filter((item) => !item.isShow).length === Total.value;//是否排雷成功
});
const CurrentTotal = ref(0);//点击时计算3*3格子内地雷数
const Total = ref(10);//地雷初始值
const userTotal = ref(10);//用户自定义地雷数
const createNum = () => {
  for (let i = 0; i < num.value * num.value; i++) {
    grid[i] = {
      index: i,//id
      isBomb: false,//是否地雷
      bombNum: 0,//周围地雷数
      isShow: false,//是否被翻开
    };//创建初始数组n*n
  }
  for (let i = 0; i < Total.value; i++) {
    createBomb(Math.floor(Math.random() * 100));//随机创建地雷
  }
};
const createBomb = (index) => {
  if (grid[index].isBomb) {//排除重复创建地雷
    createBomb(Math.floor(Math.random() * 100));
  } else {
    grid[index].isBomb = true;
  }
};
createNum();
const clickNum = (index) => {
  grid[index].isShow = true;
  if (grid[index].isBomb) {
    grid[index].bombNum = "*";
    ElMessage.error("炸弹！重置");
    resetGrid(); //遇到地雷，重置
  } else {
    countRowNum(index); //统计3*3内的地雷数
    if (grid[index].bombNum === 0) {//3*3内的地雷数为0，自动翻开3*3
      girdShow(index);//翻开本行
      girdShow(index - num.value);//翻开上行
      girdShow(index + num.value);//翻开下行
    }
  }
};
const countRowNum = (index) => {
  countNum(index);//统计本行的地雷数
  countNum(index - num.value);//统计上行
  countNum(index + num.value);//统计下行
  grid[index].bombNum = CurrentTotal.value;
  CurrentTotal.value = 0;
};
const countNum = (index) => {
  if (index > 0 && index < num.value * num.value) {
    if (grid[index].isBomb) {
      CurrentTotal.value++;
    }
    if (index % num.value !== 0) {//边界0
      if (grid[index - 1].isBomb) {
        CurrentTotal.value++;
      }
    }
    if (index % num.value !== num.value - 1) {//边界9
      if (grid[index + 1].isBomb) {
        CurrentTotal.value++;
      }
    }
  }
};
const girdShow = (index) => {//自动翻开时统计3*3地雷数
  if (index >= 0 && index < num.value * num.value) {//数组0-99
    grid[index].isShow = true;
    countRowNum(index);
    if (index % num.value !== 0) {//边界0
      grid[index - 1].isShow = true;
      countRowNum(index - 1);
    }
    if (index % num.value !== num.value - 1) {//边界9
      grid[index + 1].isShow = true;
      countRowNum(index + 1);
    }
  }
};
const resetGrid = () => {//重置
  num.value = userNum.value;
  Total.value = userTotal.value;
  grid.length = 0;
  createNum();
};
const flag = (item) => {//右键插旗，留疑，还原
  if (item.isShow) return;
  if (event.target.nodeName === "BUTTON" || event.target.nodeName === "SPAN") {
    item.isflag = item.isflag ? (item.isflag === "🚩" ? "❓" : "") : "🚩";
  }
};
const menu = (e) => {e.preventDefault()};//右键菜单禁用
window.addEventListener("contextmenu", menu);
onBeforeUnmount(() => {window.removeEventListener("contextmenu", menu);});
</script>
<style scoped>
.center {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 0 auto;
}
.button {
  width: 50px;
  margin: 0;
}
.button:hover {
  background-color: rgb(146, 146, 146);
}
.buttonClick {
  background-color: #fff;
}
</style>
